#pragma once

#include <iostream>
#include <cstring>
#include <jsoncpp/json/json.h>
#include <sys/types.h>
#include <sys/socket.h>

#define SEP " "
#define SEP_LEN strlen(SEP)
#define LINESEP "\r\n"
#define LINESEP_LEN strlen(LINESEP)

enum
{
    OK = 0,
    DIV_ZERO,
    MOD_ZERO,
    OP_ERROR,
};

//将正文封装成  "content_len\r\ncontent\r\n"
std::string enLength(const std::string& content)
{
    int content_len = content.size();
    std::string send_string = std::to_string(content_len) + LINESEP + content + LINESEP;
    return send_string;
}

//解封出正文
bool deLength(const std::string& req_str, std::string* content)
{
    size_t pos = req_str.find(LINESEP);
    if(pos == std::string::npos) return false;
    std::string content_len_str = req_str.substr(0, pos);
    int content_len = std::stoi(content_len_str);
    *content = req_str.substr(pos+LINESEP_LEN, content_len);
    return true;
}

bool recvPackage(int sock, std::string& inbuffer, std::string *req)
{
    char buffer[1024];

    while(true)
    {
        size_t n = recv(sock, buffer, sizeof(buffer) - 1, 0);
        if(n > 0)
        {
            buffer[n] = 0;
            inbuffer += buffer;
            size_t pos = inbuffer.find(LINESEP);
            //如果没找到LINESEP，说明一定不是完整报文
            if(pos == std::string::npos) continue;
            std::string content_len_str = inbuffer.substr(0, pos);
            int content_len = std::stoi(content_len_str);

            size_t total_len = content_len_str.size() + 2*LINESEP_LEN + content_len;
            //如果inbuffer大小小于total_len，说明里面没有至少一个完整报文
            if(inbuffer.size() < total_len) continue;

            *req = inbuffer.substr(0, total_len);
            inbuffer.erase(0, total_len);
            break;
        }
        else
            return false;
    }
    return true;
}

struct Request
{
    Request()
        :x(0), op(0), y(0)
        {}
    Request(int x_, char op_, int y_)
        :x(x_), op(op_), y(y_)
        {}

    //序列化
    bool serialize(std::string* out)
    {
#ifdef MYSELF
        *out = "";
        //结构化 -> "x op y"
        std::string x_string = std::to_string(x);
        std::string y_string = std::to_string(y);

        *out = x_string + SEP + op + SEP + y_string;
#else
        Json::Value root;
        root["first"] = x;
        root["oper"] = op;
        root["second"] = y;

        Json::FastWriter writer;
        //Json::StyledWriter writer;      //格式更好看
        *out = writer.write(root);

#endif
        return true;
    }

    //反序列化
    bool deserialize(const std::string& in)
    {
        //"x op y" -> 结构化
#ifdef MYSELF
        size_t left = in.find(SEP);     //第一个分隔符位置
        size_t right = in.rfind(SEP);   //第二个分隔符位置

        if(left == std::string::npos || right == std::string::npos)
            return false;

        if(left != right - 2)   //如果操作符不是一个字符，直接返回
            return false;

        std::string x_string = in.substr(0,left);
        std::string y_string = in.substr(right + SEP_LEN);

        if(x_string.empty() || y_string.empty())
            return false;

        op = in[left + SEP_LEN];
        x = std::stoi(x_string);
        y = std::stoi(y_string);
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root);

        x = root["first"].asInt();
        y = root["second"].asInt();
        op = root["oper"].asInt();      //char类型本来就是整数
#endif
        return true;
    }

    int x;
    char op;
    int y;
};

struct Response
{
    Response()
        :exitcode(0), result(0)
    {}

    Response(int exitcode_, int result_)
        :exitcode(exitcode_), result(result_)
        {}

        //序列化
    bool serialize(std::string* out)
    {
#ifdef MYSELF
        *out = "";
        //结构化 -> "exitcode result"
        std::string ec_string = std::to_string(exitcode);
        std::string res_string = std::to_string(result);

        *out = ec_string + SEP + res_string;
#else
        Json::Value root;
        root["exitcode"] = exitcode;
        root["result"] = result;

        Json::FastWriter writer;
        //Json::StyledWriter writer;      //格式更好看
        *out = writer.write(root);
#endif    
        return true;
    }

    //反序列化
    bool deserialize(const std::string& in)
    {
        //"exitcode result" -> 结构化
#ifdef MYSELF
        size_t mid = in.find(SEP);

        if(mid == std::string::npos)
            return false;

        std::string ec_string = in.substr(0,mid);
        std::string res_string = in.substr(mid + SEP_LEN);

        if(ec_string.empty() || res_string.empty())
            return false;

        exitcode = std::stoi(ec_string);
        result = std::stoi(res_string);
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root);

        exitcode = root["exitcode"].asInt();
        result = root["result"].asInt();
#endif
        return true;
    }

    int exitcode;   //0:计算成功 !0:计算出错
    int result;
};